﻿using System;
using System.Text;
using System.Text.RegularExpressions;

namespace ErrorDumper {
    public static class ExceptionProperty {
        public static readonly string Empty = "Empty";
        public static readonly string Handle = "Handle";
        public static readonly string Handler = "Handler";
        public static readonly string Machine = "Machine";
        public static readonly string RegisterUtc = "RegisterUtc";
        public static readonly string Sender = "Sender";
        public static readonly string Catcher = "Catcher";
        public static readonly string ClassName = "ClassName";
        public static readonly string ClassFullName = "ClassFullName";
        public static readonly string Message = "Message";
        public static readonly string WriteUtc = "WriteUtc";
        public static readonly string BusinessServiceName = "BusinessServiceName";
        public static readonly string BusinessServer = "BusinessServer";
        public static readonly string InnerClassFullName = "InnerClassFullName";
        public static readonly string InnerMessage = "InnerMessage";

        public static string EncodeName(string name) {
            if (String.IsNullOrEmpty(name))
                throw new ArgumentException("name is null or empty");

            Match m = s_xmlNameValidateReg.Match(name);
            if (m.Success)
                return name;

            return s_invalidCharactersReg.Replace(name, chMatch => {
                string character = chMatch.Value;
                if (character.Length != 1)
                    throw new ArgumentException("character length must be equal 1");

                byte[] buffer = Encoding.UTF8.GetBytes(character);

                if (buffer.Length == 1)
                    return "_x00" + Convert.ToString(buffer[0], 16).PadLeft(2, '0') + '_';
                else if (buffer.Length == 2)
                    return "_x" + Convert.ToString(buffer[0], 16).PadLeft(2, '0') + Convert.ToString(buffer[1], 16).PadLeft(2, '0') + '_';
                else
                    throw new InvalidOperationException("invalid buffer length " + buffer.Length.ToString());
            });
        }

        public static string DecodeName(string name) {
            if (String.IsNullOrEmpty(name))
                throw new ArgumentException("name is null or empty");

            MatchEvaluator evaluator = new MatchEvaluator(DecodeCharacter);


            return s_decodeNameReg.Replace(name, evaluator);

        }

        private static string DecodeCharacter(Match m) {
            if (m == null)
                throw new ArgumentNullException("m");

            string code = m.Groups["code"].Value;
            if (code.Length != 4)
                throw new InvalidOperationException("invalid code length " + code.Length.ToString());

            byte[] buffer = new byte[2];
            buffer[0] = Convert.ToByte(code.Substring(0, 2), 16);
            buffer[1] = Convert.ToByte(code.Substring(2, 2), 16);

            return Encoding.UTF8.GetString(buffer).Replace("\0", ""); ;
        }

        internal static bool ValidateXmlName(string name) {
            if (name == null || name.Length == 0)
                return false;
            return s_xmlNameValidateReg.Match(name).Success;
        }

        private static readonly Regex s_xmlNameValidateReg = new Regex(@"^(?!\d)[_\w][_\-\w.]+$",
            RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline);
        private static readonly Regex s_invalidCharactersReg = new Regex(@"^[\d.\-]|[^_\-.\w]",
            RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline);
        private static Regex s_decodeNameReg = new Regex(@"_x(?<code>[0-9abcdef]{4})_",
            RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline);
    }
}
